﻿using Microsoft.AspNetCore.Mvc;
using Travel.Data.Dtos;
using Travel.Data.Inputs;
using Travel.Data;
using Microsoft.AspNetCore.Authorization;
using Travel.Service.User;
using Travel.Service;
using Travel.API.Filters;
using Travel.Data.Consts;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using DotNetCore.CAP;
using Rong.EasyExcel;
using Travel.Data.Dtos.TravelBusiness;
using Rong.EasyExcel.Models;
using Microsoft.AspNetCore.SignalR;
using Travel.API.Hubs;
using Travel.CommonUtil;

namespace Travel.API.Controller
{
    /// <summary>
    /// 用户管理
    /// </summary>
    [ApiController]
    [Route("[controller]/[action]")]
    public class UserController : BaseController
    {
        private readonly IUserService _userService;
        private readonly ITokenService _tokenService;
        private readonly IWebHostEnvironment _webHostEnvironment;
        private readonly IExcelImportManager _excelImportManager;
        private readonly IHubContext<TravelHubs> _hubContext;
        public UserController(IUserService userService, ITokenService tokenService, IWebHostEnvironment webHostEnvironment, IExcelImportManager excelImportManager, IHubContext<TravelHubs> hubContext)
        {
            _userService = userService;
            _tokenService = tokenService;
            _webHostEnvironment = webHostEnvironment;
            _excelImportManager = excelImportManager;
            _hubContext = hubContext;
        }

        /// <summary>
        /// 登录(手机/邮箱/用户名)
        /// </summary>
        /// <param name="loginInput"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<Results<UserDto>> Login(LoginInput loginInput)
        {
            if (string.IsNullOrWhiteSpace(loginInput.LoginAccout) || string.IsNullOrWhiteSpace(loginInput.pwd))
            {
                return Results<UserDto>.InValidParameter();
            }
            var loginResult = await _userService.LoginAsync(loginInput);
            if (loginResult.Success)
            {
                loginResult.Token = _tokenService.GenerateToken(loginResult.Data!);
            }
            return loginResult;
        }

        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="registerInput"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        public async Task<Results<UserDto>> Refister([FromBody] RegisterInput registerInput)
        {

            return await _userService.RefisterAsync(registerInput);
        }

        /// <summary>
        /// 激活用户
        /// </summary>
        /// <param name="activeCode">激活码</param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("{activeCode}")]
        public async Task<Results<string>> ActiveUser(long activeCode)
        {
            if (activeCode <= 0L)
            {
                return Results<string>.InValidParameter();
            }
            return await _userService.ActiveUserAsync(activeCode);
        }

        /// <summary>
        /// 修改个人资料
        /// </summary>
        /// <param name="userProfileInput"></param>
        /// <remarks>登录即可调用 所有角色都可以调用</remarks>
        /// <returns></returns>
        [HttpPost]
        [TravelAuthorize]
        public async Task<Results<int>> UpdataUserProdile(UserProfileInput userProfileInput)
        {

            return await _userService.UpdataUserProdileAsync(userProfileInput);
        }
        /// <summary>
        /// 忘记密码
        /// </summary>
        /// <param name="loginAccount"></param>
        /// <returns></returns>
        /// <remarks>根据登录账号，发送授权码/验证码（用户可以拿着这个验证码去重置密码）</remarks>
        [AllowAnonymous]
        [HttpGet("{loginAccount}")]
        public async Task<Results<int>> ForgetPwd(string loginAccount)
        {
            return await _userService.ForgetPwdAsync(loginAccount);
        }

        /// <summary>
        /// 找回密码
        /// </summary>
        /// <returns></returns>
        /// <remarks>无需登录</remarks>
        [HttpPost]
        [AllowAnonymous]
        public async Task<Results<int>> UpdatePwdhenForget([FromBody] UpdatePwdhenForgetInput input)
        {
            return await _userService.UpdatePwdhenForgetAsync(input);
        }

        /// <summary>
        /// 用户分页查询
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        [TravelAuthorize(AuthorizeRoleName.Administrator)]
        public async Task<Results<PageDto<UserDto>>> UserQuery([FromBody] UserQueryInput input)
        {
            return await _userService.UserQuery(input);
        }

        /// <summary>
        /// 修改个人密码
        /// </summary>
        /// <param name="updatePwdInput"></param>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        public async Task<Results<int>> UpdatePwd([FromBody] UpdatePwdInput updatePwdInput)
        {
            return await _userService.UpdatePwdAsync(updatePwdInput);
        }
        /// <summary>
        /// 根据用户ID获取一条数据
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        [HttpGet("{userId}")]
        [TravelAuthorize]
        public async Task<Results<UserDto>> GetUserById(long userId)
        {
            return await _userService.GetUserByIdAsync(userId);
        }
        /// <summary>
        /// 根据用户ID删除一条数据
        /// </summary>
        /// <param name="userId">要删除的用户ID</param>
        /// <param name="loginUserId">当前登录人</param>
        /// <returns></returns>
        [HttpDelete("{userId}")]
        [TravelAuthorize(AuthorizeRoleName.Administrator)]
        public async Task<Results<int>> DeleteUserById(long userId)
        {
            return await _userService.DeleteUserByIdAsync(userId, LoginUserId);
        }

        /// <summary>
        /// 添加或者修改用户信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <remarks>管理员操作</remarks>
        [HttpPost]
        [TravelAuthorize(AuthorizeRoleName.Administrator)]
        public async Task<Results<int>> AddOrUpdataAsync([FromBody] UserAddOrUpdataInput input)
        {
            return await _userService.AddOrUpdataAsync(input);
        }
        /// <summary>
        /// 批量导入用户（订阅事件）
        /// </summary>
        /// <returns></returns>
        [NonAction]
        [CapSubscribe(EventBus.ImportUser, Group = EventBus.ImportUser)]
        public async Task SubcribeImportUser(ImportUserInput input)
        {
            try
            {
                await using var excelFilePath = System.IO.File.OpenRead(_webHostEnvironment.WebRootPath + input.FilePath);
                var data = await _excelImportManager.ImportAsync<TravelUserDto>(excelFilePath, c =>
                {
                    //c.SheetIndex = 0;
                    c.CheckError();
                });
                //获取excel数据
                var travelUserDtos = data.GetAllData().ToList();
                //多线程导入用户的数据 TODO

                await InsertData(travelUserDtos, input);

                await _hubContext.Clients.Client(input.ConnectionId).SendAsync(SignalMethod.ReceiveMessage, Results<string>.DataResult("导入完成"));
            }
            catch (Exception ex)
            {

            }

        }

        private readonly object _locker = new object();
        /// <summary>
        /// 多线程导入用户的数据
        /// </summary>
        /// <param name="travelUserDtos"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task InsertData(List<TravelUserDto> travelUserDtos, ImportUserInput input)
        {
            var partition = ListUtil.Partition(travelUserDtos, 10000);
            List<Task> taskList = new List<Task>();
            //总数量
            int total = travelUserDtos.Count;
            //成功的数量
            int successCount = 0;
            //失败的数量
            int failCount = 0;
            foreach (var item in partition)
            {
                var task = Task.Run(async () =>
                {
                    List<TravelUserDto> list = new List<TravelUserDto>();
                    foreach (var travel in item)
                    {
                        if (!FormatUtil.IsEmail(travel.Email) || !FormatUtil.IsPhone(travel.Mobile))
                        {
                            lock (_locker)
                            {
                                failCount++;
                            }
                            continue;
                        }
                        list.Add(travel);
                    }
                    var importList = ListUtil.Partition(list);
                    foreach (var item in importList)
                    {
                        int needImportCount = item.Count();
                        var row = (await _userService.ImportUser(item, input.LoginUserId)).Data;
                        lock (_locker)
                        {
                            successCount += row;
                            failCount += (needImportCount - row);
                        }
                        await _hubContext.Clients.Client(input.ConnectionId).SendAsync(SignalMethod.ImportUserProcess, successCount, failCount, ((successCount + failCount) / 1.0 / total).ToString("P2"));
                    }

                });
                taskList.Add(task);
            }
            //等待所有
            Task.WaitAll(taskList.ToArray());
        }
    }
}
